package com.foodorder.service;

import com.foodorder.entity.Order;
import com.foodorder.entity.Refund;
import com.foodorder.repository.OrderRepository;
import com.foodorder.repository.RefundRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 退款处理服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RefundService {
    
    private final OrderRepository orderRepository;
    private final RefundRepository refundRepository;
    private final OrderService orderService;
    private final InventoryService inventoryService;
    private final PaymentTimeoutService paymentTimeoutService;
    
    /**
     * 申请退款
     * 
     * @param orderId 订单ID
     * @param reason 退款原因
     * @param refundAmount 退款金额（null表示全额退款）
     * @return 退款申请
     */
    @Transactional(rollbackFor = Exception.class)
    public Refund applyRefund(Long orderId, String reason, BigDecimal refundAmount) {
        // 验证订单
        Order order = orderRepository.findById(orderId)
            .orElseThrow(() -> new RuntimeException("订单不存在"));
        
        // 检查订单状态是否可以退款
        if (!canRefund(order)) {
            throw new RuntimeException("订单状态不允许退款: " + order.getStatus());
        }
        
        // 检查是否已有待处理的退款申请
        if (hasActiveRefund(orderId)) {
            throw new RuntimeException("该订单已有待处理的退款申请");
        }
        
        // 确定退款金额
        BigDecimal actualRefundAmount = refundAmount != null ? refundAmount : order.getTotalAmount();
        
        // 验证退款金额
        if (actualRefundAmount.compareTo(BigDecimal.ZERO) <= 0 || 
            actualRefundAmount.compareTo(order.getTotalAmount()) > 0) {
            throw new RuntimeException("退款金额无效");
        }
        
        try {
            // 创建退款记录
            Refund refund = new Refund();
            refund.setOrderId(orderId);
            refund.setOrderNo(order.getOrderNo());
            refund.setUserId(order.getUserId());
            refund.setStoreId(order.getStoreId());
            refund.setRefundAmount(actualRefundAmount);
            refund.setOriginalAmount(order.getTotalAmount());
            refund.setReason(reason);
            refund.setStatus(Refund.RefundStatus.PENDING);
            refund.setRefundType(actualRefundAmount.equals(order.getTotalAmount()) ? 
                Refund.RefundType.FULL : Refund.RefundType.PARTIAL);
            refund.setCreatedAt(LocalDateTime.now());
            refund.setUpdatedAt(LocalDateTime.now());
            
            Refund savedRefund = refundRepository.save(refund);
            
            log.info("退款申请创建成功，订单号: {}, 退款金额: {}, 退款ID: {}", 
                order.getOrderNo(), actualRefundAmount, savedRefund.getId());
            
            return savedRefund;
            
        } catch (Exception e) {
            log.error("退款申请创建失败，订单ID: {}", orderId, e);
            throw new RuntimeException("退款申请创建失败: " + e.getMessage());
        }
    }
    
    /**
     * 审核退款申请
     * 
     * @param refundId 退款ID
     * @param approved 是否通过
     * @param adminRemark 管理员备注
     * @param operatorId 操作员ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void reviewRefund(Long refundId, boolean approved, String adminRemark, Long operatorId) {
        Refund refund = refundRepository.findById(refundId)
            .orElseThrow(() -> new RuntimeException("退款申请不存在"));
        
        if (refund.getStatus() != Refund.RefundStatus.PENDING) {
            throw new RuntimeException("退款申请状态不正确，无法审核");
        }
        
        try {
            if (approved) {
                // 通过申请，执行退款
                processRefund(refund);
                refund.setStatus(Refund.RefundStatus.PROCESSING);
            } else {
                // 拒绝申请
                refund.setStatus(Refund.RefundStatus.REJECTED);
            }
            
            refund.setAdminRemark(adminRemark);
            refund.setOperatorId(operatorId);
            refund.setReviewedAt(LocalDateTime.now());
            refund.setUpdatedAt(LocalDateTime.now());
            
            refundRepository.save(refund);
            
            log.info("退款申请审核完成，退款ID: {}, 结果: {}", refundId, approved ? "通过" : "拒绝");
            
        } catch (Exception e) {
            log.error("退款申请审核失败，退款ID: {}", refundId, e);
            throw new RuntimeException("退款审核失败: " + e.getMessage());
        }
    }
    
    /**
     * 执行退款处理
     * 
     * @param refund 退款申请
     */
    private void processRefund(Refund refund) {
        try {
            Order order = orderRepository.findById(refund.getOrderId()).orElse(null);
            if (order == null) {
                throw new RuntimeException("订单不存在");
            }
            
            // 调用支付接口执行退款（这里模拟）
            boolean paymentRefundSuccess = processPaymentRefund(refund);
            
            if (paymentRefundSuccess) {
                // 支付退款成功，处理业务逻辑
                
                // 如果是全额退款，更新订单状态为已退款
                if (refund.getRefundType() == Refund.RefundType.FULL) {
                    order.setStatus(Order.OrderStatus.REFUNDED);
                    order.setUpdatedAt(LocalDateTime.now());
                    orderRepository.save(order);
                    
                    // 释放库存
                    if (order.getOrderItems() != null) {
                        for (var item : order.getOrderItems()) {
                            inventoryService.releaseStock(item.getProductId(), item.getQuantity());
                        }
                    }
                }
                
                // 更新退款状态
                refund.setStatus(Refund.RefundStatus.COMPLETED);
                refund.setRefundedAt(LocalDateTime.now());
                
                log.info("退款处理成功，退款ID: {}, 金额: {}", refund.getId(), refund.getRefundAmount());
                
            } else {
                // 支付退款失败
                refund.setStatus(Refund.RefundStatus.FAILED);
                log.error("支付退款失败，退款ID: {}", refund.getId());
            }
            
        } catch (Exception e) {
            log.error("退款处理失败，退款ID: {}", refund.getId(), e);
            refund.setStatus(Refund.RefundStatus.FAILED);
            throw e;
        }
    }
    
    /**
     * 模拟支付退款处理
     * 
     * @param refund 退款申请
     * @return 是否成功
     */
    private boolean processPaymentRefund(Refund refund) {
        try {
            // 这里应该调用实际的支付接口进行退款
            // 微信支付、支付宝等
            
            log.info("模拟支付退款处理，退款ID: {}, 金额: {}", refund.getId(), refund.getRefundAmount());
            
            // 模拟退款成功
            return true;
            
        } catch (Exception e) {
            log.error("支付退款处理异常，退款ID: {}", refund.getId(), e);
            return false;
        }
    }
    
    /**
     * 查找用户的退款申请
     * 
     * @param userId 用户ID
     * @return 退款申请列表
     */
    public List<Refund> findUserRefunds(Long userId) {
        return refundRepository.findByUserIdOrderByCreatedAtDesc(userId);
    }
    
    /**
     * 查找店铺的退款申请
     * 
     * @param storeId 店铺ID
     * @return 退款申请列表
     */
    public List<Refund> findStoreRefunds(Long storeId) {
        return refundRepository.findByStoreIdOrderByCreatedAtDesc(storeId);
    }
    
    /**
     * 查找待审核的退款申请
     * 
     * @return 待审核退款申请列表
     */
    public List<Refund> findPendingRefunds() {
        return refundRepository.findByStatusOrderByCreatedAtAsc(Refund.RefundStatus.PENDING);
    }
    
    /**
     * 检查订单是否可以退款
     * 
     * @param order 订单
     * @return 是否可以退款
     */
    private boolean canRefund(Order order) {
        // 只有已支付、制作中、已完成的订单可以申请退款
        return order.getStatus() == Order.OrderStatus.PAID ||
               order.getStatus() == Order.OrderStatus.PREPARING ||
               order.getStatus() == Order.OrderStatus.COMPLETED;
    }
    
    /**
     * 检查订单是否已有活跃的退款申请
     * 
     * @param orderId 订单ID
     * @return 是否有活跃退款申请
     */
    private boolean hasActiveRefund(Long orderId) {
        List<Refund> activeRefunds = refundRepository.findActiveRefundsByOrderId(orderId);
        return !activeRefunds.isEmpty();
    }
    
    /**
     * 取消退款申请（仅限待审核状态）
     * 
     * @param refundId 退款ID
     * @param userId 用户ID（验证权限）
     */
    @Transactional(rollbackFor = Exception.class)
    public void cancelRefund(Long refundId, Long userId) {
        Refund refund = refundRepository.findById(refundId)
            .orElseThrow(() -> new RuntimeException("退款申请不存在"));
        
        if (!refund.getUserId().equals(userId)) {
            throw new RuntimeException("无权操作此退款申请");
        }
        
        if (refund.getStatus() != Refund.RefundStatus.PENDING) {
            throw new RuntimeException("只能取消待审核的退款申请");
        }
        
        refund.setStatus(Refund.RefundStatus.CANCELLED);
        refund.setUpdatedAt(LocalDateTime.now());
        refundRepository.save(refund);
        
        log.info("退款申请已取消，退款ID: {}", refundId);
    }
    
    /**
     * 获取退款统计信息
     * 
     * @param storeId 店铺ID（null表示全部）
     * @return 统计信息
     */
    public RefundStats getRefundStats(Long storeId) {
        try {
            long totalRefunds = storeId != null ? 
                refundRepository.countByStoreId(storeId) : 
                refundRepository.count();
                
            long pendingRefunds = storeId != null ?
                refundRepository.countByStoreIdAndStatus(storeId, Refund.RefundStatus.PENDING) :
                refundRepository.countByStatus(Refund.RefundStatus.PENDING);
                
            long completedRefunds = storeId != null ?
                refundRepository.countByStoreIdAndStatus(storeId, Refund.RefundStatus.COMPLETED) :
                refundRepository.countByStatus(Refund.RefundStatus.COMPLETED);
            
            BigDecimal totalRefundAmount = storeId != null ?
                refundRepository.sumRefundAmountByStoreId(storeId) :
                refundRepository.sumTotalRefundAmount();
            
            return new RefundStats(totalRefunds, pendingRefunds, completedRefunds, 
                totalRefundAmount != null ? totalRefundAmount : BigDecimal.ZERO);
                
        } catch (Exception e) {
            log.error("获取退款统计失败", e);
            return new RefundStats(0, 0, 0, BigDecimal.ZERO);
        }
    }
    
    /**
     * 退款统计信息类
     */
    public static class RefundStats {
        private final long totalRefunds;
        private final long pendingRefunds;
        private final long completedRefunds;
        private final BigDecimal totalRefundAmount;
        
        public RefundStats(long totalRefunds, long pendingRefunds, 
                          long completedRefunds, BigDecimal totalRefundAmount) {
            this.totalRefunds = totalRefunds;
            this.pendingRefunds = pendingRefunds;
            this.completedRefunds = completedRefunds;
            this.totalRefundAmount = totalRefundAmount;
        }
        
        // Getters
        public long getTotalRefunds() { return totalRefunds; }
        public long getPendingRefunds() { return pendingRefunds; }
        public long getCompletedRefunds() { return completedRefunds; }
        public BigDecimal getTotalRefundAmount() { return totalRefundAmount; }
        
        @Override
        public String toString() {
            return String.format("RefundStats{total=%d, pending=%d, completed=%d, amount=%s}",
                totalRefunds, pendingRefunds, completedRefunds, totalRefundAmount);
        }
    }
} 